<template>
    <div>
        <el-upload class="avatar-uploader" action="#" :http-request="handleXhr" :show-file-list="false" accept="image/*"
            :before-upload="beforeAvatarUpload">
            <div v-if="filePath" class="preview" style="">
                <!-- <span>
                    <el-icon @click.prevent="onClickDelete()">
                        <Delete />
                    </el-icon>
                    <el-icon @click.prevent="onClickZoom()">
                        <ZoomIn />
                    </el-icon>
                </span> -->
                <img :src="filePath" class="avatar" />
            </div>
            <el-icon v-else class="avatar-uploader-icon el-icon-plus">
                <Plus />
            </el-icon>

        </el-upload>

        <el-dialog v-model="dialogVisible">
            <img w-full :src="dialogImageUrl" style="width:100%; max-height:60vh;" alt="Preview Image" />
        </el-dialog>
    </div>
</template>
  
<script setup>
/**
 * 头像上传组件
 */
import { ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { Plus, Delete, ZoomIn } from '@element-plus/icons-vue'
import EsAjax from '@/utils/EsAjax';
import ApiUrls from '@/apis/index';

// ======================================================
//                      功能函数
// ======================================================

/**
 * 字节单位转换
 */
const bytesToSize = (bytes) => {
    if (bytes === 0) {
        return '0 B';
    }
    var k = 1024, // or 1024
        sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
        i = Math.floor(Math.log(bytes) / Math.log(k));

    return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i];
}

// ======================================================
//                      变量声明
// ======================================================

// props
const props = defineProps({
    modelValue: String,
    maxSize: {
        type: Number,
        default: 500 * 1024,
    }
})
// emit（v-model 使用在原生控件为: value @input，使用在组件为: modelValue @update:modelValue）
const emit = defineEmits(['update:modelValue']);
// 文件路径
const filePath = ref(props.modelValue)
// watch
watch(() => props.modelValue, (newVal) => {
    filePath.value = newVal;
})
// 文件类型
const imageMimes = ['image/gif', 'image/jpg', 'image/jpeg', 'image/bmp', 'image/png', 'image/webp']
// 文件大小提示
const maxSizeText = bytesToSize(props.maxSize);
// 图片预览弹窗
const dialogImageUrl = ref('')
const dialogVisible = ref(false)

// ======================================================
//                      处理事件
// ======================================================

// 处理上传文件之前的钩子
const beforeAvatarUpload = (rawFile) => {
    if (!imageMimes.includes(rawFile.type)) {
        ElMessage.error('文件不是有效的图片格式！')
        return false;
    }
    if (rawFile.size > props.maxSize) {
        ElMessage.error('单个文件不能超过 ' + maxSizeText + '!')
        return false;
    }
    return true
}
// 处理上传文件的请求
const handleXhr = (xhr) => {
    let formData = new FormData();
    formData.set('file', xhr.file);
    EsAjax.post(ApiUrls.upload, formData).then(res => {
        if (res.data.errcode) {
            ElMessage.warning(res.data.message);
            return;
        }
        filePath.value = res.data.data[0].url;
        emit('update:modelValue', filePath.value);
    }).catch(err => { ElMessage.error('网络错误：' + err.message) })
}

const onClickDelete = () => {
    filePath.value = '';
    emit('update:modelValue', filePath.value);
}
const onClickZoom = () => {
    dialogImageUrl.value = filePath.value
    dialogVisible.value = true
}
</script>
  